﻿using SQLite.DbEntities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Common;

namespace SQLite.Reps.Base
{
    public abstract class Rep<TDbEntity> : IRep where TDbEntity : DbEntity, new()
    {
        protected SQLite.SQLiteAsyncConnection _connection;
        public Rep(SQLite.SQLiteAsyncConnection connection)
        {
            _connection = connection;
        }

        public String TableName
        {
            get
            {
                return typeof(TDbEntity).Name;
            }
        }

        public async Task Remove(TDbEntity dbEntity)
        {
            await _connection.DeleteAsync(dbEntity);
        }

        public async Task RemoveAll(IEnumerable<TDbEntity> dbEntities)
        {
            await _connection.DeleteAllAsync(dbEntities);
        }

        public Type TableType { get { return typeof(TDbEntity); } }

        public virtual async Task UpdateAsync(TDbEntity dbEntity)
        {
            await _connection.UpdateAsync(dbEntity);
        }

        public virtual async Task SaveAsync(TDbEntity dbEntity)
        {
            if (dbEntity.Id == Guid.Empty)
            {
                dbEntity.Id = Guid.NewGuid();
                await _connection.InsertAsync(dbEntity);
            }
            else
            {
                await _connection.UpdateAsync(dbEntity);
            }
        }

        public virtual async Task<Boolean> Exists(Guid id)
        {
            var res = await GetByIdAsync(id);
            return res != null;
        }

        public virtual async Task InsertAsync(TDbEntity dbEntity)
        {
            if (dbEntity.Id.IsEmpty())
                throw new ArgumentNullException();

            await _connection.InsertAsync(dbEntity);
        }

        public virtual async Task<TDbEntity> GetByIdAsync(Guid id)
        {
            if (id == Guid.Empty)
                return null;

            var res = await _connection.FindAsync<TDbEntity>(id);
            return res;
        }

        public virtual async Task<List<TDbEntity>> GetAll()
        {
            return await Table().ToListAsync();
        }

        protected SQLite.AsyncTableQuery<TDbEntity> Table()
        {
            return _connection.Table<TDbEntity>();
        }

        public async Task DeleteById(Guid id)
        {
            var sqlDeleteCommand = String.Format("Delete From {0} where Id = ?", typeof(TDbEntity).Name);
            await _connection.ExecuteAsync(sqlDeleteCommand, id);
        }

        public async Task ClearAsync()
        {
            var sqlDeleteCommand = String.Format("Delete From {0}", typeof(TDbEntity).Name);
            await _connection.ExecuteAsync(sqlDeleteCommand);
        }

        public async Task<Int32> Count() 
        {
            return await Table().CountAsync();
        }
    }
}
